﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Windows.Forms;

using ClassLibrary;

namespace TestProject
{
    public static class Data
    {
        public static string new_name = null;
    }
    public static class Functions
    {
        public static TreeView treeView1=null;
        public static void add_node_func(object tag, string name, string type)
        {
            switch (type)
            {
                case "gent":
                    treeView1.Nodes[0].Nodes[0].Nodes[0].Nodes.Add(name).Tag = tag;
                    break;
                case "chromt":
                    treeView1.Nodes[0].Nodes[0].Nodes[1].Nodes.Add(name).Tag = tag;
                    break;
                case "crossl":
                    treeView1.Nodes[0].Nodes[1].Nodes[3].Nodes.Add(name).Tag = tag;
                    break;
                case "phent":
                    treeView1.Nodes[0].Nodes[0].Nodes[2].Nodes.Add(name).Tag = tag;
                    break;
                case "natselt":
                    treeView1.Nodes[0].Nodes[0].Nodes[3].Nodes.Add(name).Tag = tag;
                    break;
                case "chrgenl":
                    treeView1.Nodes[0].Nodes[1].Nodes[0].Nodes.Add(name).Tag = tag;
                    break;
                case "genphl":
                    treeView1.Nodes[0].Nodes[1].Nodes[1].Nodes.Add(name).Tag = tag;
                    break;
                case "natsell":
                    treeView1.Nodes[0].Nodes[1].Nodes[2].Nodes.Add(name).Tag = tag;
                    break;
                case "reprodl":
                    treeView1.Nodes[0].Nodes[1].Nodes[4].Nodes.Add(name).Tag = tag;
                    break;
                case "spec":
                    treeView1.Nodes[0].Nodes[2].Nodes.Add(name).Tag = tag;
                    break;
                case "pop":
                    treeView1.SelectedNode.Nodes.Add(name).Tag = tag;
                    break;
                case "indi":
                    treeView1.SelectedNode.Nodes.Add(name).Tag = tag;
                    break;
            }
        }
        public static bool gene_is_used(ChromosomeGeneLink link, GeneType g)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(link.path));
            foreach (XmlNode node in doc.GetElementsByTagName("gene_categories"))
            {
                foreach (string s in node.InnerText.Split(' '))
                {
                    if (s == g.allele_type_id.ToString())
                        return true;
                }
            }
            return false;
        }
        public static bool gene_is_used(GeneTable gen_t, Dictionary<string,ChromosomeGeneLink> links,GeneType g)
        {
            XmlDocument doc = new XmlDocument();
            List<string> paths = new List<string>();
            foreach (ChromosomeGeneLink chromlink in links.Values)
            {
                if (chromlink.path_to_gene_table == gen_t.path)
                {
                    int j = -1;
                    doc.LoadXml(System.IO.File.ReadAllText(chromlink.path));
                    foreach (XmlNode node in doc.GetElementsByTagName("gene_categories"))
                    {
                        j++;
                        int k = -1;
                        foreach (string s in node.InnerText.Split(' '))
                        {
                            k++;
                            if (s == g.allele_type_id.ToString())
                                paths.Add("Link: " + chromlink.name + ", Chromosome ID: " + j.ToString() + ", Locus: " + k.ToString());
                        }
                    }
                }
            }
            if (paths.Count > 0)
            {
                string error = "Error: gene is used in following links:";
                foreach (string s in paths)
                {
                    error += "\n" + s;
                }
                MessageBox.Show(error);
                return true;
            }
            return false;
        }
        public static int set_id(ChromosomeTable chrom_t)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(chrom_t.path));
            int id = 0;
            for (; ; id++)
            {
                bool b = true;
                foreach (XmlNode node in doc.GetElementsByTagName("chromosome"))
                {
                    if (id.ToString() == node.Attributes[0].Value)
                    {
                        b = false;
                        break;
                    }
                }
                if (b)
                    return id;
            }
        }
        public static int set_id(GeneTable gen_t)
        {           
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(gen_t.path));
            int id = 0;
            for (; ; id++)
            {
                bool b = true;
                foreach (XmlNode node in doc.GetElementsByTagName("gene"))
                {
                    if (id.ToString() == node.Attributes[0].Value)
                    {
                        b = false;
                        break;
                    }
                }
                if (b)
                    return id;
            }        
        }
        public static bool allele_is_used(Dictionary<string,Species> species,GeneType g, int allele)
        {
            XmlDocument doc = new XmlDocument();
            List<string> paths = new List<string>();
            foreach (Species sp in species.Values)
            {
                foreach (Population pop in sp.massive_populations.Values)
                {
                    foreach (Individual indi in pop.massive_individuals)
                    {
                        foreach (string key in indi.massive_chromosomes.Keys)
                        {
                            foreach (Chromosome chrom in indi.massive_chromosomes[key])
                            {
                                for (int i = 0; i < chrom.amount_locuses; i++)
                                {
                                    if (sp.sp_chomosome_gene_link.link[chrom.pare_id.ToString()][i] == g.allele_type_id)
                                    {
                                        if (chrom.massive_locus[i].gene.allele == allele)
                                            paths.Add("Specie: " + sp.name + ", Population: " + pop.name + ", Individual: " + indi.name + ", Chromosome pair ID: " + key + ", Chromosome ID: " + chrom.pare_id.ToString() + ", Locus: " + i.ToString());
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (paths.Count > 0)
            {
                string error = "Error: allele is used in following individuals:";
                foreach (string s in paths)
                {
                    error += "\n" + s;
                }
                MessageBox.Show(error);
                return true;
            }
            return false;
        }
        public static int set_id(PhenotypeTable phen_t)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(phen_t.path));
            int id = 0;
            for (; ; id++)
            {
                bool b = true;
                foreach (XmlNode node in doc.GetElementsByTagName("characteristic"))
                {
                    if (id.ToString() == node.Attributes[0].Value)
                    {
                        b = false;
                        break;
                    }
                }
                if (b)
                    return id;
            }
        }
        public static int set_id(NaturalSelectionTable natsel_t)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(natsel_t.path));
            int id = 0;
            for (; ; id++)
            {
                bool b = true;
                foreach (XmlNode node in doc.GetElementsByTagName("natural_selection_variant"))
                {
                    if (id.ToString() == node.Attributes[0].Value)
                    {
                        b = false;
                        break;
                    }
                }
                if (b)
                    return id;
            }
        }
        public static void textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            TextBox textBox = (TextBox)sender;
            if (!(Char.IsDigit(e.KeyChar)) && !((e.KeyChar == '.') && (textBox.Text.IndexOf(".") == -1) && (textBox.Text.Length != 0)))
            {
                if (e.KeyChar != (char)Keys.Back)
                {
                    e.Handled = true;
                }
            }
        }
        public static int set_id(ReproductionLink rep_link)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.IO.File.ReadAllText(rep_link.path));
            int id = 0;
            for (; ; id++)
            {
                bool b = true;
                foreach (XmlNode node in doc.GetElementsByTagName("reproduction_event"))
                {
                    if (id.ToString() == node.Attributes[0].Value)
                    {
                        b = false;
                        break;
                    }
                }
                if (b)
                    return id;
            }
        }
        public static List<List<int>> combine(int[] arr)
        {
            int comb = 1;
            foreach (int i in arr)
            {
                comb *= (i + 1);
            }
            List<List<int>> combinations = new List<List<int>>(comb);
            if (arr.Count() > 2)
            {
                int[] temp = new int[arr.Length - 1];
                for (int i = 0; i < arr.Length - 1; i++)
                {
                    temp[i] = arr[i];
                }
                List<List<int>> temp1 = combine(temp);
                for (int i = 0; i <= arr.Last(); i++)
                {
                    for (int j = 0; j < temp1.Count(); j++)
                    {
                        List<int> l = new List<int>();
                        foreach (int k in temp1[j])
                        {
                            l.Add(k);
                        }
                        l.Add(i);
                        combinations.Add(l);
                    }
                }
            }
            else
            {
                for (int i = 0; i <= arr[1]; i++)
                {
                    for (int j = 0; j <= arr[0]; j++)
                    {
                        combinations.Add(new List<int>());
                        combinations[i * (arr[0] + 1) + j].Add(j);
                        combinations[i * (arr[0] + 1) + j].Add(i);
                    }
                }
            }
            return combinations;
        }        
    }
}
